package com.photoeditor.demo.ui.widget.image.edit;

import android.content.Context;
import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Handler;
import android.os.Message;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;

import com.common.base.utils.DeviceUtils;
import com.photoeditor.R;
import com.photoeditor.demo.util.FontUtil;
import com.photoeditor.demo.util.ImageRectUtils;

import java.util.ArrayList;

/**
 * 微调整的SeekBar
 */
public class MicroSeekBar extends View {

    //当前的进度值
    public float mCurrentProgress = 50f;

    //最大的进度值
    public float mMaxProgress = 100f;

    //最小的进度值
    public float mMinProgress = 0f;

    //确定了中间位置就确定了 整个应该绘制成什么样子
    private float mCenterDegree = 0.0f;
    public int mMinDegree = -45;
    public int mMaxDegree = 45;

    //View的Rect
    public RectF mRect;

    //绘制小刻度的Paint
    public Paint mLittlePaint;

    //绘制大刻度的Paint
    public Paint mLargePaint;

    //刻度尺的Paint
    public Paint mLinePaint;

    //绘制数字的Paint
    public TextPaint mNumPaint;

    //用于临时存储大刻度的位置
    public ArrayList<Float> mLargePositionList;

    //用于临时存储小刻度的位置
    public ArrayList<Float> mLittlePositionList;

    //用于绘制时存储大刻度的位置
    public float[] mLargePosition;

    //用于绘制时存储小刻度的位置
    public float[] mLittlePosition;

    //用于存储数字的StaticLayout
    public ArrayList<StaticLayout> mTextLayout;

    //用于存储StaticLayout应该绘制的X值
    public ArrayList<Float> mTextLeft;

    //刻度尺的Y
    public float mLineY;

    //Text的Y
    public float mTextY;

    //是否初始化
    private boolean mInit = false;

    //用于存储刻度的位置
    private float mPointStartX;
    private float mPointStartY;
    private float mPointEndX;
    private float mPointEndY;

    //两个刻度之间的间距
    private final int POSITION_SPACE;

    //大刻度的Y轴的大小
    private final int POSITION_Y_LARGE;

    //小刻度Y轴的大小
    private final int POSITION_Y_LITTLE;

    //数字和大刻度之间的间距
    private final int DISTANCE_WIDTH_NUMBER;
    private final int DISTANCE_WIDTH_POINT;

    private Drawable mPointDrawable;
    private Rect mPointDrawableRect;
    public float mPointY;
    public float mPointX;

    /**
     * 回调
     */
    private OnSeekBarChangeListener mListener;

    /**
     * 用于处理Touch事件
     */
    //是否被touch
    private boolean mIsTouch = false;
    private float mDownX;
    //按下的进度值
    private float mDownProgress;
    private final int TYPE_MOVE = 2;
    private final int TYPE_DOWN = 1;
    private final int TYPE_NONE = 0;
    private int mTouchType = TYPE_NONE;

    private final static int MSG_REFRESH = 1;
    private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            if (msg.what == MSG_REFRESH) {
                postInvalidate();
            }
        }
    };

    public MicroSeekBar(Context context) {
        this(context, null);
    }

    public MicroSeekBar(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MicroSeekBar(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
        Resources resources = getResources();
        POSITION_SPACE = resources.getDimensionPixelSize(R.dimen.micro_position_space);
        POSITION_Y_LARGE = resources.getDimensionPixelSize(R.dimen.micro_position_y_large);
        POSITION_Y_LITTLE = resources.getDimensionPixelSize(R.dimen.micro_position_y_little);
        DISTANCE_WIDTH_NUMBER = resources.getDimensionPixelSize(R.dimen.micro_distance_with_number);
        DISTANCE_WIDTH_POINT = resources.getDimensionPixelSize(R.dimen.micro_distance_with_point);
    }

    public void init() {
        setWillNotDraw(false);

        mPointDrawable = getResources().getDrawable(R.drawable.ic_image_edit_tool_rotate_scale_micro_point);
        mPointDrawableRect = new Rect(0, 0, mPointDrawable.getIntrinsicWidth(), mPointDrawable.getIntrinsicHeight());

        Resources resources = getResources();
        int lineColor = resources.getColor(R.color.micro_scale_color);
        int width = DeviceUtils.dip2px(getContext(), 2);
        mLittlePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLittlePaint.setStrokeWidth(width);
        mLittlePaint.setColor(lineColor);

        mLargePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLargePaint.setStrokeWidth(width);
        mLargePaint.setColor(lineColor);

        mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mLinePaint.setStrokeWidth(width);
        mLinePaint.setColor(resources.getColor(R.color.micro_center_scale_color));

        mNumPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
        mNumPaint.setTextSize(resources.getDimensionPixelSize(R.dimen.micro_number_size));
        mNumPaint.setColor(resources.getColor(R.color.micro_number_color));
        mNumPaint.setTypeface(FontUtil.CUSTOM_FONT);

        mRect = new RectF();

        mLargePositionList = new ArrayList<Float>();
        mLittlePositionList = new ArrayList<Float>();
        mTextLayout = new ArrayList<StaticLayout>();
        mTextLeft = new ArrayList<Float>();
    }

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
        if (changed) {
            doInit(ImageRectUtils.getViewRect(this));
        }
    }


    /**
     * 重写onMeasure确保能完全显示 默认80dp
     */
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        int height = getResources().getDimensionPixelSize(R.dimen.image_edit_bottom_bar_height);
        heightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                MeasureSpec.EXACTLY);
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    }

    /**
     * 执行一些初始化
     *
     * @param viewRect
     */
    private void doInit(RectF viewRect) {
        if (!mInit || !mRect.equals(viewRect)) {
            mInit = true;
            mRect.set(viewRect);
            mLineY = mRect.height() / 2;

            /**
             * 第五个参数用于控制是否换行  如果文字长度超过这个值就会换行
             */
            String textString = "0";
            float width = StaticLayout.getDesiredWidth(textString, mNumPaint);
            StaticLayout layout = new StaticLayout(textString, 0, textString.length(), mNumPaint, (int) (width + 1), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f,
                    false, TextUtils.TruncateAt.END, (int) (width + 1));
            mTextY = mLineY - POSITION_Y_LARGE / 2 - DISTANCE_WIDTH_NUMBER - layout.getHeight() + DeviceUtils.dip2px(getContext(), 2);
            mPointStartY = mLineY - POSITION_Y_LARGE / 2;
            mPointStartX = mRect.width() / 2;
            mPointEndX = mRect.width() / 2;
            mPointEndY = mLineY + POSITION_Y_LARGE / 2;

            mPointY = mLineY + POSITION_Y_LARGE / 2 + DISTANCE_WIDTH_POINT;
            mPointX = mRect.width() / 2 - mPointDrawableRect.width() / 2;
            dealProgressChangeNew(true);

            initView(getResources().getColor(R.color.accent_color));
        }
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if (mInit) {
            canvas.drawLines(mLargePosition, mLargePaint);
            canvas.drawLines(mLittlePosition, mLittlePaint);

            canvas.drawLine(mPointStartX, mPointStartY, mPointEndX, mPointEndY, mLinePaint);
//            canvas.drawLine(0, mLineY, mRect.width(), mLineY, mLinePaint);

            int num = mTextLayout.size();
            for (int i = 0; i < num; i++) {
                int count = canvas.save();
                canvas.translate(mTextLeft.get(i), mTextY);
                mTextLayout.get(i).draw(canvas);
                canvas.restoreToCount(count);
            }

            int count = canvas.save();
            canvas.translate(mPointX, mPointY);
            mPointDrawable.setBounds(mPointDrawableRect);
            mPointDrawable.draw(canvas);
            canvas.restoreToCount(count);
        }
    }


    /**
     * 设置当前的进度
     *
     * @param progress
     * @param isFromUser
     */
    public void setProgress(float progress, boolean isFromUser) {
        if (mInit) {
            mCurrentProgress = progress;
            mCurrentProgress = Math.max(mMinProgress, mCurrentProgress);
            mCurrentProgress = Math.min(mMaxProgress, mCurrentProgress);
            mCenterDegree = countCurrentDegree(mCurrentProgress);
            dealProgressChangeNew(isFromUser);
        } else {
            this.mCurrentProgress = progress;
            mCurrentProgress = Math.max(mMinProgress, mCurrentProgress);
            mCurrentProgress = Math.min(mMaxProgress, mCurrentProgress);
            this.mCenterDegree = countCurrentDegree(mCurrentProgress);
        }
    }

    /**
     * 增加进度
     *
     * @param addProgress
     * @param isFromUser
     */
    public void addProgress(int addProgress, boolean isFromUser) {
        if (mInit) {
            this.mCurrentProgress += addProgress;
            mCurrentProgress = Math.max(mMinProgress, mCurrentProgress);
            mCurrentProgress = Math.min(mMaxProgress, mCurrentProgress);
            this.mCenterDegree = countCurrentDegree(mCurrentProgress);
            dealProgressChangeNew(isFromUser);
        } else {
            this.mCurrentProgress += addProgress;
            mCurrentProgress = Math.max(mMinProgress, mCurrentProgress);
            mCurrentProgress = Math.min(mMaxProgress, mCurrentProgress);
            this.mCenterDegree = countCurrentDegree(mCurrentProgress);
        }
    }

    /**
     * 进度变化后的处理
     *
     * @param isFromUser
     */
    private void dealProgressChangeNew(boolean isFromUser) {
        float width = mRect.width();
        mLargePositionList.clear();
        mLittlePositionList.clear();
        mTextLayout.clear();
        mTextLeft.clear();
        float centerWidth = width / 2;
        int currentDegree = (int) mCenterDegree;
        float houzui = mCenterDegree - currentDegree;

        float yuanhua = mCenterDegree - Math.round(mCenterDegree);
        if (Math.abs(yuanhua) <= 0.15f) {
            houzui = 0f;
            mCenterDegree = Math.round(mCenterDegree);
            currentDegree = (int) mCenterDegree;
        }

        int flagDegree;
        float lastPosition = centerWidth - POSITION_SPACE / 2 * houzui;//这个是(int)mCenterDegree 的位置
        if (currentDegree % 2 != 0) {
            lastPosition = lastPosition - POSITION_SPACE / 2;
            currentDegree -= 1;
        }
        flagDegree = currentDegree;
        int i = 0;//large
        int j = 0;//little
        float key = lastPosition;

        while (key >= 0f) {
            if ((int) currentDegree == 0 || ((int) currentDegree % 10) == 0) {//中间是大的
                mLargePositionList.add(key);
                mLargePositionList.add(mLineY - POSITION_Y_LARGE / 2);
                mLargePositionList.add(key);
                mLargePositionList.add(mLineY + POSITION_Y_LARGE / 2);
                String text = String.valueOf((int) currentDegree);
                float textWidth = StaticLayout.getDesiredWidth(text, mNumPaint);
                StaticLayout layout = new StaticLayout(text, 0, text.length(), mNumPaint, (int) (textWidth + 1), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f,
                        false, TextUtils.TruncateAt.END, (int) (textWidth + 1));
                mTextLayout.add(layout);
                mTextLeft.add(key - textWidth / 2);
                i++;
            } else {//中间是小的
                mLittlePositionList.add(key);
                mLittlePositionList.add(mLineY - POSITION_Y_LITTLE / 2);
                mLittlePositionList.add(key);
                mLittlePositionList.add(mLineY + POSITION_Y_LITTLE / 2);
                j++;
            }
            currentDegree -= 2;
            key -= POSITION_SPACE;
        }
        key = lastPosition + POSITION_SPACE;
        currentDegree = flagDegree + 2;
        while (key <= width) {
            if ((int) currentDegree == 0 || ((int) currentDegree % 10) == 0) {//中间是大的
                mLargePositionList.add(key);
                mLargePositionList.add(mLineY - POSITION_Y_LARGE / 2);
                mLargePositionList.add(key);
                mLargePositionList.add(mLineY + POSITION_Y_LARGE / 2);
                i++;
                String text = String.valueOf((int) currentDegree);
                float textWidth = StaticLayout.getDesiredWidth(text, mNumPaint);
                StaticLayout layout = new StaticLayout(text, 0, text.length(), mNumPaint, (int) (textWidth + 1), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f,
                        false, TextUtils.TruncateAt.END, (int) (textWidth + 1));
                mTextLayout.add(layout);
                mTextLeft.add(key - textWidth / 2);
            } else {//中间是小的
                mLittlePositionList.add(key);
                mLittlePositionList.add(mLineY - POSITION_Y_LITTLE / 2);
                mLittlePositionList.add(key);
                mLittlePositionList.add(mLineY + POSITION_Y_LITTLE / 2);
                j++;
            }
            currentDegree += 2;
            key += POSITION_SPACE;
        }
        int largeLen = mLargePositionList.size();
        int littleLen = mLittlePositionList.size();
        mLargePosition = new float[largeLen];
        mLittlePosition = new float[littleLen];
        for (int k = 0; k < largeLen; k++) {
            mLargePosition[k] = mLargePositionList.get(k).floatValue();
        }
        for (int k = 0; k < littleLen; k++) {
            mLittlePosition[k] = mLittlePositionList.get(k).floatValue();
        }

        refresh();
        if (mListener != null) {
            mListener.onProgressChanged(this, mCenterDegree, isFromUser);
        }
    }

    public float countCurrentDegree(float progress) {
        return (progress * 1.0f / mMaxProgress * (mMaxDegree - mMinDegree) + mMinDegree);
    }

    public void setOnSeekBarChangeListener(OnSeekBarChangeListener listener) {
        mListener = listener;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            mDownX = event.getX();
            mDownProgress = mCurrentProgress;
            mTouchType = TYPE_DOWN;
            mIsTouch = true;
            return true;
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            float fdownX = event.getX();
            if (mTouchType == TYPE_DOWN) {
                if (mListener != null) {
                    mListener.onStartTrackingTouch(this);
                }
                setProgress(mDownProgress - (fdownX - mDownX) / (POSITION_SPACE * (mMaxDegree - mMinDegree - 1)) * mMaxProgress, true);
                mTouchType = TYPE_MOVE;
            } else if (mTouchType == TYPE_MOVE) {
                setProgress(mDownProgress - (fdownX - mDownX) / (POSITION_SPACE * (mMaxDegree - mMinDegree - 1)) * mMaxProgress, true);
            }
        } else if (event.getAction() == MotionEvent.ACTION_CANCEL || event.getAction() == MotionEvent.ACTION_UP) {
            mIsTouch = false;
            mTouchType = TYPE_NONE;
            if (mListener != null) {
                mListener.onStopTrackingTouch(this);
            }
        }
        return super.onTouchEvent(event);
    }

    /**
     * 重置进度
     */
    public void resetProgress() {
        setProgress((mMaxProgress - mMinProgress) / 2 + mMinProgress, false);
    }

    public void refresh() {
        if (!mHandler.hasMessages(MSG_REFRESH)) {
            mHandler.sendEmptyMessage(MSG_REFRESH);
        }
    }

    private void initView(int emphasisColor) {
        mPointDrawable = getResources().getDrawable(R.drawable.ic_image_edit_tool_rotate_scale_micro_point);
        dealProgressChangeNew(false);
        mLinePaint.setColor(emphasisColor);
        mPointDrawable.setColorFilter(emphasisColor, PorterDuff.Mode.SRC_IN);
    }
}
